// utils/validate/enter.go  // 验证工具包入口文件
// =============================================================================
// | 包: validate                                                            |
// | 功能: 验证工具包入口文件                                                |
// | 说明: 提供数据验证和错误信息翻译功能                                    |
// =============================================================================
package validate // 定义validate包

import ( // 导入依赖包
	"fmt"     // 格式化包
	"reflect" // 反射包
	"strings" // 字符串处理包

	"github.com/gin-gonic/gin/binding"                                       // Gin绑定包
	"github.com/go-playground/locales/zh"                                    // 中文本地化包
	ut "github.com/go-playground/universal-translator"                       // 通用翻译器包
	"github.com/go-playground/validator/v10"                                 // 验证器包
	zh_translations "github.com/go-playground/validator/v10/translations/zh" // 中文翻译包
) // 结束导入

// =============================================================================
// | 变量: trans                                                              |
// | 类型: ut.Translator                                                      |
// | 功能: 定义翻译器实例，用于错误信息的本地化                              |
// =============================================================================
var trans ut.Translator // 声明翻译器实例

// =============================================================================
// | 函数: init                                                              |
// | 功能: 包初始化函数，用于初始化验证器和翻译器                            |
// | 说明: 创建翻译器，注册翻译器，注册自定义标签名称处理函数                |
// =============================================================================
func init() { // 包初始化函数
	// 创建翻译器
	uni := ut.New(zh.New())            // 创建新的翻译器
	trans, _ = uni.GetTranslator("zh") // 获取中文翻译器

	// 注册翻译器
	v, ok := binding.Validator.Engine().(*validator.Validate) // 获取验证器引擎
	if ok {                                                   // 检查是否成功获取验证器
		_ = zh_translations.RegisterDefaultTranslations(v, trans) // 注册默认翻译
	}
	// 注册自定义标签名称函数
	// v.RegisterTagNameFunc(func(field reflect.StructField) string {
	// 	// 从结构体字段的标签中获取"label"键的值
	// 	label := field.Tag.Get("label")
	// 	// 如果标签值为空，则返回字段的原始名称
	// 	if label == "" {
	// 		return field.Name
	// 	}
	// 	// 返回标签中定义的label值
	// 	return label
	// })

	// 注册自定义标签名称处理函数
	v.RegisterTagNameFunc(func(field reflect.StructField) string { // 注册标签名称函数
		// 从结构体字段标签中获取"label"标签的值
		label := field.Tag.Get("label") // 获取label标签

		// 如果label标签为空或只有空格，则使用字段名作为标签
		if label == "" { // 检查label是否为空
			label = field.Name // 使用字段名作为标签
		}

		// 从结构体字段标签中获取"json"标签的值
		name := field.Tag.Get("json") // 获取json标签

		// 返回格式化后的标签字符串，格式为"json标签名-字段标签名"
		return fmt.Sprintf("%s---%s", name, label) // 返回格式化标签
	})

} // 结束初始化函数

// =============================================================================
// | 函数: ValidateErr                                                        |
// | 参数: @err - error (验证过程中产生的错误)                                |
// | 返回: @string - 格式化的错误消息字符串                                   |
// | 功能: 处理验证错误并返回格式化后的错误信息                              |
// =============================================================================
func ValidateErr(err error) string { // 验证错误处理函数
	errs, ok := err.(validator.ValidationErrors) // 类型断言为验证错误
	if !ok {                                     // 检查是否为验证错误
		return err.Error() // 返回原始错误信息
	}
	var list []string        // 声明字符串切片
	for _, e := range errs { // 遍历所有验证错误
		list = append(list, e.Translate(trans)) // 翻译错误并添加到列表
	}
	return strings.Join(list, ";") // 用分号连接错误信息
} // 结束验证错误处理函数

// =============================================================================
// | 函数: ValidateError                                                      |
// | 参数: @err - error (验证过程中产生的错误)                                |
// | 返回: @data - map[string]any (格式化的错误数据映射)                      |
// |       @msg - string (合并的错误消息字符串)                               |
// | 功能: 处理验证错误并返回格式化后的错误信息                              |
// | 说明: 将验证错误转换为本地化的错误信息，并按字段名组织错误数据          |
// =============================================================================
func ValidateError(err error) (data map[string]any, msg string) { // 验证错误处理函数
	// 尝试将错误转换为验证错误类型
	errs, ok := err.(validator.ValidationErrors) // 类型断言为验证错误

	// 如果不是验证错误类型，直接返回原始错误信息
	if !ok { // 检查是否为验证错误
		msg = err.Error() // 设置错误消息
		return            // 返回错误信息
	}

	// 初始化数据映射和消息列表
	data = make(map[string]any) // 创建数据映射
	var msgList []string        // 声明消息列表

	// 遍历所有验证错误
	for _, e := range errs { // 遍历验证错误
		// 翻译错误信息
		translatedMsg := e.Translate(trans) // 翻译错误信息

		// 分割错误信息（格式为"字段名--错误描述"）
		parts := strings.Split(translatedMsg, "---") // 分割翻译后的消息

		if len(parts) >= 2 { // 检查分割后的部分数量
			// 将错误信息按字段名存入映射
			data[parts[0]] = parts[1] // 存储字段名和错误描述
			// 收集所有错误描述
			msgList = append(msgList, parts[1]) // 添加错误描述到列表
		}
	}

	// 将所有错误描述用分号连接成单个字符串
	msg = strings.Join(msgList, ";") // 连接错误描述

	return data, msg // 返回数据和消息
} // 结束验证错误处理函数
